

#include "salof.h" 

#ifdef SALOF_USING_LOG

#ifndef SALOF_BUFF_SIZE
    #define     SALOF_BUFF_SIZE     (1024U)
#endif 
#ifndef SALOF_FIFO_SIZE
    #define     SALOF_FIFO_SIZE     (2048U)
#endif 

static int salof_out(char *buf, int len);

#if SALOF_USING_SALOF
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#define _XOPEN_SOURCE 
#define __USE_XOPEN
#include <time.h>
#include <unistd.h>
#include <dirent.h>


static salof_fifo_t _salof_fifo = NULL;
static int _len;
static char _out_buff[SALOF_BUFF_SIZE];
static char _file_names[LOGFILE_MAXCOUNT][LOGFILE_NAMELENTH];
static char _file_prifix[LOGFILE_NAMELENTH];
static FILE* _file_fp = NULL;
#if !SALOF_USING_IDLE_HOOK
static salof_tcb _salof_task;
void salof_task(void *parm);
#else

#if !defined(salof_handler)
    #error "salof_handler need to be defined as your hook function"
#endif

#endif
#endif

static char _salof_format_buff[SALOF_BUFF_SIZE];

int salof_init(void)
{
   // printf("salof: %d\n\r", SALOF_USING_SALOF);
#if SALOF_USING_SALOF
    _salof_fifo = salof_fifo_create(SALOF_FIFO_SIZE);
    if(_salof_fifo == NULL)
        return -1;

#if !SALOF_USING_IDLE_HOOK
    _salof_task = salof_task_create("salof_task", salof_task, NULL, SALOF_TASK_STACK_SIZE, SALOF_TASK_PRIO, SALOF_TASK_TICK);
    //printf(" create salof task %x\n", salof_task);
    if(_salof_task == NULL)
        return -1;
#endif

// log_fb = fopen("log.txt", "a");
// if (!log_fb) {
//     printf("failed to open file,filename= log.txt\n");
//}
#endif
    return 0;
}


void salof(const char *fmt, ...)
{
    va_list args;
    int len;
    va_start(args, fmt);

    len = salof_format_nstr(_salof_format_buff, SALOF_BUFF_SIZE - 1, fmt, args);
    //printf("salof to send string\n");
    if(len > SALOF_BUFF_SIZE)
        len = SALOF_BUFF_SIZE - 1;

#if SALOF_USING_SALOF
    salof_fifo_write(_salof_fifo, _salof_format_buff, len, 100);
#else
    salof_out(_salof_format_buff, len);
#endif

  va_end(args);
}

static int salof_write_buff(const char* buf, int len)
{
    if ( _file_fp != NULL )
    {
        fputs(buf, _file_fp);
	    fflush(_file_fp);
    }
    

    return len;
}

static int salof_out(char *buf, int len)
{
    //printf("ssalof_out %s -- %d\n", buf, len);
    return salof_write_buff(buf, len);
}

static int salof_file_alives_proc(void)
{
    int ret = 0;
    char curtime[20];  //当前日期时间
    char deadtime[20]; //截止的历史日期

    salof_get_curtime(curtime);
    //只取日期，省去时间
    memset(&curtime[8],0x30,6);
    //printf("ailve maxdays:%d\n",LOGFILE_ALIVEDAYS);
    //printf("curtime:%s\n",curtime);

    struct tm* tmp_time = (struct tm*)malloc(sizeof(struct tm));
    //字符串转时间
    strptime(curtime,"%Y%m%d%H%M%S",tmp_time);
    //printf("hour:%d\n", tmp_time->tm_hour);
    time_t t = mktime(tmp_time);
    //printf("t now = %ld\n",t);

    free(tmp_time);

    time_t t1 = t - LOGFILE_ALIVEDAYS*24*60*60;
    //再把t1转换为时间，即时间戳转时间
    //printf("t1 = %ld\n",t1);
    struct tm *p;
    p = localtime(&t1);
    //printf("year:%d m: %d  d: %d\n", p->tm_year+1900, p->tm_mon, p->tm_mday);
    //日期时间转字符串,由于只比较日期，因此忽略时间
    strftime(deadtime, sizeof(deadtime), "%Y%m%d000000", p);
    //printf("deadtime:%s\n",deadtime);

    //以上获取到了curtime和deadtime,有了这个时间范围，接下来就去找这个范围的日志
    //日志文件日期在这个范围内的保留，否则删除
    for(int i = 0; i < LOGFILE_MAXCOUNT; i++ )
    {
        if(strlen(_file_names[i]) > 0)
        {
            //printf("file_name=%s\n",_file_names[i]);
            char ftime[20];
            memset(ftime,0,20);
            memset(ftime,0x30,8);
            //关键，这个截取不能错
            memcpy(ftime,&_file_names[i][strlen(LOGFILE_PREFIX)+1],8);
            //printf("file_time=%s\n",ftime);

            //开始比较 是否在日期范围内
            if(memcmp(ftime,deadtime,8) > 0)
            {
                //大于截止日期的文件保留
                printf("%s------keep alive\n",_file_names[i]);
            }else{
                printf("%s----------------dead,need remove!\n",_file_names[i]);
                //删除文件
                char dfname[55];
                sprintf(dfname,"%s/%s",LOGFILE_PATH,_file_names[i]);
                remove(dfname);
            }
            //
        }else{
            //printf("The current directory is empty\n");
        }

    }

    return ret;
}

static int salof_read_file_list(const char* path)
{
    DIR *dir;
    struct dirent *ptr;
    char base[1000];
    int count = 0;
    //printf("%s\n", __FUNCTION__);
    if ((dir=opendir(path)) == NULL)
    {
        fprintf(stderr,"Open dir error...");
        return -1;
    }

    while ( (ptr=readdir(dir)) != NULL )
    {   
        //++count;
        //printf("TYPE=%d\n", ptr->d_type);
        if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
            continue;
        else if(ptr->d_type == 8)    ///file
        {
            //printf("f_name:%s%s\n",path,ptr->d_name);
            sprintf(_file_names[count],"%s",ptr->d_name);
            count++;
            if(count > LOGFILE_MAXCOUNT -1){
                fprintf(stderr,"error!only allow files count=%d\n",LOGFILE_MAXCOUNT);
                return -2;
            }
        }
        else if(ptr->d_type == 10)    ///link file
            printf("l_name:%s/%s\n",path,ptr->d_name);
        else if(ptr->d_type == 4)    ///dir
        {
            //printf("d_name:%s/%s\n",path,ptr->d_name);
            printf("this is a dir\n");
            continue;
            //是目录，继续递归读目录下面的
            //memset(base,'\0',sizeof(base));
            //strcpy(base,basePath);
            //strcat(base,"/");
            //strcat(base,ptr->d_name);
            //read_filelist(base);
        }
    }

    //printf("readdir count=%d\n",count);
    closedir(dir);
    return 0;
}

static int salof_creat_dir(const char* path)
{
    char dirName[256];
    strcpy(dirName, path);
    int i,len = strlen(dirName);
    //printf("dire name: %s\n", path);
    for(i = 1; i < len; i++)
    {
        if(dirName[i]=='/')
        {
            dirName[i] = 0;
            if( access(dirName, 0)!=0 )
            {
                if(mkdir(dirName, 0755)==-1)
                {
                    fprintf(stderr,"mkdir   error\n");
                    return -1;
                }
                else
                {
                    printf("mkdir %s success\n", dirName);
                }
            }
            dirName[i] = '/';
        }
    }

    return 0;
}


#if SALOF_USING_SALOF
static int salof_create_file(void);
void salof_clear_signal(int sig)
{
    static int count = 0;

    ++count;
    if ( SIGALRM == sig )
    {
        salof_create_file();
        if ( count == LOGFILE_ALIVEDAYS )
        {
            salof_read_file_list(LOGFILE_PATH);
            salof_file_alives_proc();
        }
        
        
        //printf("salof_clear_signal\n");
        alarm(24*60*60+5);
    }
}

void salof_handler( void )
{   
   
    //printf("salof_handler\n");
    _len = salof_fifo_read(_salof_fifo, _out_buff, sizeof(_out_buff), 0);
    // printf("salof_handler len: %d\n", _len);
    if(_len > 0) {
        salof_out((char *)_out_buff, _len);
        memset(_out_buff, 0, _len);
    }
}
#endif

static int salof_create_file(void)
{
    char tmpTime[14 + 1];
    char tmpfname[80];
    //printf("salof_create_file\n");
    if ( _file_fp != NULL ) 
    {
        printf("_file_fp is not null\n");
        fclose(_file_fp);
    }
   
    salof_get_curtime(tmpTime);
    sprintf(tmpfname, "%s/%s_%8.8s.log", LOGFILE_PATH_NAME, LOGFILE_PREFIX, tmpTime);
    printf("Created file: %s\n", tmpfname);
    _file_fp = fopen( tmpfname, "a" );
    if ( NULL == _file_fp )
    {
            fprintf(stderr,"failed to open file,filename=%s\n",tmpfname);
            return -2;
    }

    return 0;
}

#if !SALOF_USING_IDLE_HOOK
void salof_task(void *parm)
{   
    (void)parm;
    //printf("%s\n", __FUNCTION__);   
    salof_creat_dir(LOGFILE_PATH);
    salof_read_file_list(LOGFILE_PATH);
    salof_file_alives_proc();
    salof_create_file();
    signal(SIGALRM, salof_clear_signal);
    alarm(24*60*60+5);
    while(1)
    {
#if SALOF_USING_SALOF
        salof_handler();
#endif
    } 
}
#endif

#endif

